﻿#pragma once
/**
 \file rationnel.h
 \brief Rationnel
 \author Baptiste Pirault et  Hugo Dubois
 \date 01/06/2012
 \version 1
 **/
#include <iostream>
#include <ostream>

#include "exception.h"
#include "fonctions.h"
#include <QString>

using namespace std;

/*!
 \class Rationnel
 \brief La classe gére la représentation des rationnels et les opérations disponibles
 */

class Rationnel{
private:

	//! \brief Numérateur
	//!
	//! Numérateur de la fraction : int
	int p; 
	
	//! \brief Dénominateur
	//!
	//! Dénominateur de la fration : int
	int q; 
	
public:

    //! \brief Constructeur.
    //!
    //! \param n entier avec 0 pour valeur par défaut
    //! \param d entier avec 1 pour valeur par défaut
      Rationnel(int n = 0,int d = 1);

    //! \brief Constructeur à partir d'une QString
    //!
    //! \param s QString
      Rationnel(const QString & s);
	
	//! \brief Affichage du rationnel
	//!
	//! \param out flux ostream, cout par défaut
	void affiche(ostream& out = cout)const;
	
	//! \brief Accesseur de p
	//!
	//! \return int valeur entiére du numérateur p

	int P()const;
	
	//! \brief Accesseur de q
	//! 	
	//! \return int valeur entiére du dénominateur q

	int Q()const;
	//! \brief Mutateur de p et q
	//!
	//! \param n int : valeur entiére du numérateur
	//! \param d int :  valeur entiére du dénominateur
    void set(const int n, const int d=1);
	
    //! \brief Valeur réelle du rationnel
	//!
	//! \return double : Retourne la valeur du rationnel sous un double
	double value()const;
	
	//! \brief Conversion du rationnel en QString pour l'affichage
	//!
	//! \return QString& Référence. Stockage du rationnel dans une chaine de caractére.
    QString& toQString(QString separator = "/")const;
		
	//! \brief Vérifie si le Rationnel est un entier (dénominateur est égal à 1)
	//!
	//! \return bool : vrai si le rationnel est un entier (q=1)
	//! \return bool : faux si différent d'un entier (q !=1)
	bool isInt()const;
	
	//! \brief Vérifie si le rationnel est nul(numérateur à 0)
	//!
	//! \return bool : vrai si le rationnel est nul (p=0)
	//! \return bool : faux si non nul (p!=0)
    bool isNull()const;
	
	//Opération 1opérande
	
	//! \brief Surcharge de l'opérateur +=
	//!
	//! Additionne le rationnel avec un autre rationnel. Stock les résulats dans le rationnel
	//! \param &r Rationnel à additionner
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator+=(const Rationnel &r);
	
	//! \brief Surcharge de l'opérateur +=
	//!
	//! Additionne le rationnel avec un réel. Stock les résulats dans le rationnel
	//! \param x : Entier à additionner
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator+=(const float x);
	
	//! \brief Surcharge de l'opérateur -=
	//!
	//! Soustrait le rationnel avec un autre rationnel. Stock les résulats dans le rationnel
	//! \param &r Rationnel à soustraire
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator-=(const Rationnel &r);
	
	//! \brief Surcharge de l'opérateur -=
	//!
	//! Soustrait le rationnel avec un réel. Stock les résulats dans le rationnel
	//! \param x : Entier à soustraire
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode	
	Rationnel& operator-=(const float x);
	
	//! \brief Surcharge de l'opérateur *=
	//!
	//! Multiplie le rationnel avec un autre rationnel. Stock les résulats dans le rationnel
	//! \param &r Rationnel à multiplier
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator*=(const Rationnel &r);
	
	//! \brief Surcharge de l'opérateur *=
	//!
	//! Multiplie le rationnel avec un réel. Stock les résulats dans le rationnel
	//! \param x Réel à multiplier
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator*=(const float x);
	
	//! \brief Surcharge de l'opérateur /=
	//!
	//! Divise le rationnel avec un autre rationnel. Stock les résulats dans le rationnel
	//! \param &r Rationnel à diviser
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator/=(const Rationnel &r);
	
	//! \brief Surcharge de l'opérateur /=
	//!
	//! Divise le rationnel avec un réel. Stock les résulats dans le rationnel
	//! \param x Réel à diviser
	//! \return Rationnel&  : Référence sur le Rationnel appellant la méthode
	Rationnel& operator/=(const float x);
	
private:
	//! \brief Simplifie le rationnel
	//!
	//! Modifie directement les attribut p et q 
	void simplifier();
};
	//! \brief Surcharge des << pour un flux
	//!
	//! Retourne l'affichage du rationnel
	//! \param &out : flux ostream
	//! \param r : Rationnel à afficher
	//! \return Affiche le rationnel et retourne un flux


ostream& operator<<(ostream& out, Rationnel r);

// opération 2opérandes

	//! \brief Surcharge de l'opérateur +
	//!
	//! Additionne deux rationnels . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param &r2 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator+(const Rationnel &r1, const Rationnel &r2);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Additionne un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param x : réel float 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator+(const Rationnel &r1, const float x);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Additionne un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param x : réel float 
	//! \param &r1 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator+(const float x, const Rationnel &r1);

	//! \brief Surcharge de l'opérateur -
	//!
	//! Soustrait deux rationnels . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param &r2 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator-(const Rationnel &r1, const Rationnel &r2);

	//! \brief Surcharge de l'opérateur -
	//!
	//! Soustrait un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param x : réel float 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator-(const Rationnel &r1, const float x);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Soustrait un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param x : réel float 
	//! \param &r1 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator-(const float x, const Rationnel &r1);

	//! \brief Surcharge de l'opérateur *
	//!
	//! Multiplie deux rationnels . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param &r2 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator*(const Rationnel &r1, const Rationnel &r2);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Multiplie un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param x : réel float 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator*(const Rationnel &r1, const float x);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Multiplie un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param x : réel float 
	//! \param &r1 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator*(const float x, const Rationnel &r1);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Divise deux rationnels . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param &r2 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator/(const Rationnel &r1, const Rationnel &r2);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Divise un rationnel par un réel . Stock le résulat dans un nouveau rationnel
	//! \param &r1 : référence sur un Rationnel 
	//! \param x : réel float 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator/(const Rationnel &r1, const float x);

	//! \brief Surcharge de l'opérateur +
	//!
	//! Divise un rationnel et un réel . Stock le résulat dans un nouveau rationnel
	//! \param x : réel float 
	//! \param &r1 : référence sur un Rationnel 
	//! \return Rationnel&  : Référence sur un nouveau rationnel contenant le résultat
Rationnel& operator/(const float x, const Rationnel &r1);

// surcharge des fonctions de math.h
	//! \brief Surcharge de la fonction puissance de maths.h
	//!
	//! Met en puissance un rationnel par un autre rationnel
	//! \param &r1 : Référence sur un rationnel
	//! \param &r2 : Référence sur un rationnel, puissance
	//! \return Retourne une référence sur un rationnel contenant le résulat.
Rationnel& pow(Rationnel &r1,Rationnel &r2);

	//! \brief Surcharge de la fonction puissance de maths.h
	//!
	//! Met en puissance un rationnel par un entier
	//! \param &r : Référence sur un rationnel
	//! \param x: Entier, puissance
	//! \return Retourne une référence sur un rationnel contenant le résulat.
Rationnel& pow(Rationnel &r,int x);

// Convertion depuis un double
	//! \brief Convertie un réel en Rationnel
	//!
	//! Permet de passer d'un réel en un rationnel. 
	//! \warning Perte d'information possible
	//! \param x : double réel.
	//! \return Retourne une référence sur un rationnel 	
Rationnel& RationnelFromDouble(const double x);

QString toQString(const Rationnel x);
